package com.ruoyi.web.controller.business.rule.factory;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.business.rule.domain.JbLogisticsRules;
import com.ruoyi.business.rule.domain.JbLogisticsRulesJson;
import com.ruoyi.business.rule.service.JbLogisticsRulesService;
import com.ruoyi.web.controller.business.statistics.vo.JbGrossProfitRateVO;
import com.ruoyi.web.core.JoController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;

/**
 * 业务 物流规则 工厂
 *
 * @author Jyl
 */
@Component
public class JbLogisticsRulesFactory extends JoController
{
    @Autowired
    private JbLogisticsRulesService jbLogisticsRulesService;

    /**
     * 获取规则
     *
     * @param id       物流规则id
     * @param areaCode 地市编码
     * @return JbLogisticsRulesJson
     */
    public JbLogisticsRulesJson getRules(Long id, String areaCode)
    {
        //获取物流规则
        JbLogisticsRulesJson jbLogisticsRulesJson = new JbLogisticsRulesJson();

        //获取物流规则
        JbLogisticsRules logisticsRules = jbLogisticsRulesService.getById(id);
        if (ObjectUtil.isEmpty(logisticsRules))
        {
            //冗余 保底默认一条
            logisticsRules = jbLogisticsRulesService.list(new LambdaQueryWrapper<JbLogisticsRules>()
                    .eq(JbLogisticsRules::isStatus, true)
            ).get(0);
        }

        //遍历规则条目
        for (JbLogisticsRulesJson json : logisticsRules.getBillingRule())
        {
            Map<String, String> map = new HashMap<>();
            for (String s : json.getAreaCode()) map.put(s, "");
            if (map.isEmpty() || map.containsKey(areaCode))
            {
                jbLogisticsRulesJson = json;
                jbLogisticsRulesJson.setType(logisticsRules.getBillingMethod());
            }
        }

        return jbLogisticsRulesJson;
    }

    /**
     * 计算物流费用
     *
     * @param jbLogisticsRulesJson
     * @param jbGrossProfitRateVO
     * @return
     */
    public BigDecimal fnShippingFee(JbLogisticsRulesJson jbLogisticsRulesJson, JbGrossProfitRateVO jbGrossProfitRateVO)
    {
        //续重、续费 首重、首费、
        BigDecimal exceedWeight = new BigDecimal(jbLogisticsRulesJson.getExceedWeight());
        BigDecimal exceedCharge = new BigDecimal(jbLogisticsRulesJson.getExceedCharge());
        BigDecimal firstWeight = new BigDecimal(jbLogisticsRulesJson.getFirstWeight());
        BigDecimal firstCharge = new BigDecimal(jbLogisticsRulesJson.getFirstCharge());

        //计费类型 1001 重量 1002 件数
        return switch (jbLogisticsRulesJson.getType())
        {
            case "1001" ->
                    fnType(exceedWeight, exceedCharge, firstWeight, firstCharge, jbGrossProfitRateVO.getUnitContent());
            case "1002" -> fnType(exceedWeight, exceedCharge, firstWeight, firstCharge, jbGrossProfitRateVO.getCount());
            default -> BigDecimal.ZERO;
        };
    }

    /**
     * 计算运费
     *
     * @param exceedWeight 续重、件
     * @param exceedCharge 续费
     * @param firstWeight  首重、件
     * @param firstCharge  首费
     * @param fnTotal      货物重量，件数
     * @return
     */
    public BigDecimal fnType(BigDecimal exceedWeight, BigDecimal exceedCharge, BigDecimal firstWeight,
                             BigDecimal firstCharge, BigDecimal fnTotal)
    {
        BigDecimal total = firstCharge;
        if (fnTotal.compareTo(firstWeight) > 0)
        {
            //超出部分费用 ：=>减出超重=>除出超重份数=>乘出超重费用=>加上首重费用
            total = fnTotal.subtract(firstWeight);
            if (BigDecimal.ZERO.compareTo(exceedWeight) != 0)
            {
                total = total.divide(exceedWeight, 0, RoundingMode.UP);
                if (BigDecimal.ZERO.compareTo(exceedCharge) != 0)
                {
                    total = total.multiply(exceedCharge);
                } else
                {
                    total = BigDecimal.ZERO;
                }
            } else
            {
                total = BigDecimal.ZERO;
            }
            total = total.add(firstCharge);
        }
        return total;
    }

}
